/**
* @Author: qinhaoda
* @Description:
* @File: mon_discover
* @Version: 1.0.0
* @Date: 2023/3/1 11:57
 */
package models

import (
	"encoding/json"
	"strconv"
	"time"
	"xorm.io/builder"
)

type StreeDiscovery struct {
	Id          int64     `json:"id"`
	Nid         int64     `json:"nid"`
	Name        string    `json:"name"`
	Type        string    `json:"type"`
	ServiceId   int64     `json:"service_id"`
	CollectPath string    `json:"collect_path"`
	Port        int       `json:"port"`
	MetricsPath string    `json:"metrics_path"`
	Idc         string    `json:"idc"`
	Role        string    `json:"role"`
	Cluster     string    `json:"cluster"`
	Shard       string    `json:"shard"`
	Keyword     string    `json:"keyword"`
	Creator     string    `json:"creator"`
	Created     time.Time `xorm:"updated" json:"created"`
	LastUpdator string    `xorm:"last_updator" json:"last_updator"`
	LastUpdated time.Time `xorm:"updated" json:"last_updated"`
}

type LvsDiscovery struct {
	Id          int64     `json:"id"`
	Nid         int64     `json:"nid"`
	Name        string    `json:"name"`
	Type        string    `json:"type"`
	ServiceId   int64     `json:"service_id"`
	Path        string    `json:"path"`
	Port        int       `json:"port"`
	MetricsPath string    `json:"metrics_path"`
	Idc         string    `json:"idc"`
	Keyword     string    `json:"keyword"`
	Creator     string    `json:"creator"`
	Created     time.Time `xorm:"updated" json:"created"`
	LastUpdator string    `xorm:"last_updator" json:"last_updator"`
	LastUpdated time.Time `xorm:"updated" json:"last_updated"`
}

type ManualDiscovery struct {
	Id          int64     `json:"id"`
	Nid         int64     `json:"nid"`
	Name        string    `json:"name"`
	Type        string    `json:"type"`
	ServiceId   int64     `json:"service_id"`
	Port        int       `json:"port"`
	MetricsPath string    `json:"metrics_path"`
	Idc         string    `json:"idc"`
	Machines    string    `json:"machines"`
	Creator     string    `json:"creator"`
	Created     time.Time `xorm:"updated" json:"created"`
	LastUpdator string    `xorm:"last_updator" json:"last_updator"`
	LastUpdated time.Time `xorm:"updated" json:"last_updated"`
}

type UrlDiscovery struct {
	Id          int64     `json:"id"`
	Nid         int64     `json:"nid"`
	Name        string    `json:"name"`
	Type        string    `json:"type"`
	ServiceId   int64     `json:"service_id"`
	Port        int       `json:"port"`
	MetricsPath string    `json:"metrics_path"`
	Idc         string    `json:"idc"`
	Url         string    `json:"url"`
	Target      string    `json:"target"`
	Creator     string    `json:"creator"`
	Created     time.Time `xorm:"updated" json:"created"`
	LastUpdator string    `xorm:"last_updator" json:"last_updator"`
	LastUpdated time.Time `xorm:"updated" json:"last_updated"`
}

type StarkDiscovery struct {
	Id          int64     `json:"id"`
	Nid         int64     `json:"nid"`
	Name        string    `json:"name"`
	Type        string    `json:"type"`
	ServiceId   int64     `json:"service_id"`
	Port        int       `json:"port"`
	MetricsPath string    `json:"metrics_path"`
	Idc         string    `json:"idc"`
	App         string    `json:"app"`
	Deployment  string    `json:"deployment"`
	Cluster     string    `json:"cluster"`
	Creator     string    `json:"creator"`
	Created     time.Time `xorm:"updated" json:"created"`
	LastUpdator string    `xorm:"last_updator" json:"last_updator"`
	LastUpdated time.Time `xorm:"updated" json:"last_updated"`
}

func CreateDiscovery(discoveryType, creator string, discovery interface{}, dryRun bool) (err error) {
	session := DB["mon"].NewSession()
	if err = session.Begin(); err != nil {
		session.Close()
		return err
	}
	defer func() {
		if err != nil || dryRun {
			session.Rollback()
		} else {
			err = session.Commit()
		}
		session.Close()
	}()

	if _, err = session.Insert(discovery); err != nil {
		return
	}

	var b []byte
	if b, err = json.Marshal(discovery); err != nil {
		return
	}

	err = saveHistory(0, discoveryType, "create", creator, string(b), session)
	return
}

func (s *StreeDiscovery) Update() error {
	session := DB["mon"].NewSession()
	defer session.Close()

	err := session.Begin()
	if err != nil {
		return err
	}

	if _, err = session.Id(s.Id).AllCols().Update(s); err != nil {
		session.Rollback()
		return err
	}

	b, err := json.Marshal(s)
	if err != nil {
		session.Rollback()
		return err
	}

	if err := saveHistory(s.Id, "stree", "update", s.Creator, string(b), session); err != nil {
		session.Rollback()
		return err
	}

	if err = session.Commit(); err != nil {
		return err
	}

	return err
}

func (l *LvsDiscovery) Update() error {
	session := DB["mon"].NewSession()
	defer session.Close()

	err := session.Begin()
	if err != nil {
		return err
	}

	if _, err = session.Id(l.Id).AllCols().Update(l); err != nil {
		session.Rollback()
		return err
	}

	b, err := json.Marshal(l)
	if err != nil {
		session.Rollback()
		return err
	}

	if err := saveHistory(l.Id, "lvs", "update", l.Creator, string(b), session); err != nil {
		session.Rollback()
		return err
	}

	if err = session.Commit(); err != nil {
		return err
	}

	return err
}

func (u *UrlDiscovery) Update() error {
	session := DB["mon"].NewSession()
	defer session.Close()

	err := session.Begin()
	if err != nil {
		return err
	}

	if _, err = session.Id(u.Id).AllCols().Update(u); err != nil {
		session.Rollback()
		return err
	}

	b, err := json.Marshal(u)
	if err != nil {
		session.Rollback()
		return err
	}

	if err := saveHistory(u.Id, "url", "update", u.Creator, string(b), session); err != nil {
		session.Rollback()
		return err
	}

	if err = session.Commit(); err != nil {
		return err
	}

	return err
}

func (m *ManualDiscovery) Update() error {
	session := DB["mon"].NewSession()
	defer session.Close()

	err := session.Begin()
	if err != nil {
		return err
	}

	if _, err = session.Id(m.Id).AllCols().Update(m); err != nil {
		session.Rollback()
		return err
	}

	b, err := json.Marshal(m)
	if err != nil {
		session.Rollback()
		return err
	}

	if err := saveHistory(m.Id, "manual", "update", m.Creator, string(b), session); err != nil {
		session.Rollback()
		return err
	}

	if err = session.Commit(); err != nil {
		return err
	}

	return err
}

func (s *StarkDiscovery) Update() error {
	session := DB["mon"].NewSession()
	defer session.Close()

	err := session.Begin()
	if err != nil {
		return err
	}

	if _, err = session.Id(s.Id).AllCols().Update(s); err != nil {
		session.Rollback()
		return err
	}

	b, err := json.Marshal(s)
	if err != nil {
		session.Rollback()
		return err
	}

	if err := saveHistory(s.Id, "stark", "update", s.Creator, string(b), session); err != nil {
		session.Rollback()
		return err
	}

	if err = session.Commit(); err != nil {
		return err
	}

	return err
}

func DeleteDiscoveryById(discoveryType, creator string, cid int64) error {
	session := DB["mon"].NewSession()
	defer session.Close()

	sql := "delete from " + discoveryType + "_discovery where id = ?"
	_, err := DB["mon"].Exec(sql, cid)
	if err != nil {
		session.Rollback()
		return err
	}

	if err := saveHistory(cid, discoveryType, "delete", creator, strconv.FormatInt(cid, 10), session); err != nil {
		session.Rollback()
		return err
	}

	return session.Commit()
}

func UpdateStreeDiscoveryForeignKey(strees []*StreeDiscovery, serviceId int64) error {
	session := DB["mon"].NewSession()
	defer session.Close()

	err := session.Begin()
	if err != nil {
		return err
	}
	clearSql := "update `stree_discovery` set service_id=0 where service_id=?"
	if _, err = session.Exec(clearSql, serviceId); err != nil {
		session.Rollback()
		return err
	}

	params := make([]int64, 0)
	for i := 0; i < len(strees); i++ {
		params = append(params, strees[i].Id)
	}
	updateBuild := builder.Update(builder.Eq{"service_id": serviceId}).From("stree_discovery").Where(builder.Eq{"id": params})
	if len(params) != 0 {
		if _, err = session.Query(updateBuild); err != nil {
			session.Rollback()
			return err
		}
	}

	err = session.Commit()
	return err
}

func UpdateLvsDiscoveryForeignKey(lvses []*LvsDiscovery, serviceId int64) error {
	session := DB["mon"].NewSession()
	defer session.Close()

	err := session.Begin()
	if err != nil {
		return err
	}
	clearSql := "update `lvs_discovery` set service_id=0 where service_id=?"
	if _, err = session.Exec(clearSql, serviceId); err != nil {
		session.Rollback()
		return err
	}

	params := make([]int64, 0)
	for i := 0; i < len(lvses); i++ {
		params = append(params, lvses[i].Id)
	}
	updateBuild := builder.Update(builder.Eq{"service_id": serviceId}).From("lvs_discovery").Where(builder.Eq{"id": params})
	if len(params) != 0 {
		if _, err = session.Query(updateBuild); err != nil {
			session.Rollback()
			return err
		}
	}

	err = session.Commit()
	return err
}

func UpdateStarkDiscoveryForeignKey(starks []*StarkDiscovery, serviceId int64) error {
	session := DB["mon"].NewSession()
	defer session.Close()

	err := session.Begin()
	if err != nil {
		return err
	}
	clearSql := "update `stark_discovery` set service_id=0 where service_id=?"
	if _, err = session.Exec(clearSql, serviceId); err != nil {
		session.Rollback()
		return err
	}

	params := make([]int64, 0)
	for i := 0; i < len(starks); i++ {
		params = append(params, starks[i].Id)
	}
	updateBuild := builder.Update(builder.Eq{"service_id": serviceId}).From("stark_discovery").Where(builder.Eq{"id": params})
	if len(params) != 0 {
		if _, err = session.Query(updateBuild); err != nil {
			session.Rollback()
			return err
		}
	}

	err = session.Commit()
	return err
}

func UpdateUrlDiscoveryForeignKey(urls []*UrlDiscovery, serviceId int64) error {
	session := DB["mon"].NewSession()
	defer session.Close()

	err := session.Begin()
	if err != nil {
		return err
	}
	clearSql := "update `url_discovery` set service_id=0 where service_id=?"
	if _, err = session.Exec(clearSql, serviceId); err != nil {
		session.Rollback()
		return err
	}

	params := make([]int64, 0)
	for i := 0; i < len(urls); i++ {
		params = append(params, urls[i].Id)
	}
	updateBuild := builder.Update(builder.Eq{"service_id": serviceId}).From("url_discovery").Where(builder.Eq{"id": params})
	if len(params) != 0 {
		if _, err = session.Query(updateBuild); err != nil {
			session.Rollback()
			return err
		}
	}

	err = session.Commit()
	return err
}

func UpdateManualDiscoveryForeignKey(manuals []*ManualDiscovery, serviceId int64) error {
	session := DB["mon"].NewSession()
	defer session.Close()

	err := session.Begin()
	if err != nil {
		return err
	}
	clearSql := "update `manual_discovery` set service_id=0 where service_id=?"
	if _, err = session.Exec(clearSql, serviceId); err != nil {
		session.Rollback()
		return err
	}

	params := make([]int64, 0)
	for i := 0; i < len(manuals); i++ {
		params = append(params, manuals[i].Id)
	}
	updateBuild := builder.Update(builder.Eq{"service_id": serviceId}).From("manual_discovery").Where(builder.Eq{"id": params})
	if len(params) != 0 {
		if _, err = session.Query(updateBuild); err != nil {
			session.Rollback()
			return err
		}
	}

	err = session.Commit()
	return err
}
